package com.mexico.inloancash.http;


import com.mexico.inloancash.utils.LogTrack;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;

import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;

/**
 * 作者：Alex
 * 时间：2017/4/10 11:20
 * 简述：
 */
@SuppressWarnings({"StringConcatenationInsideStringBufferAppend", "ConstantConditions"})
public class HttpLogInterceptor implements Interceptor {
    private static final Charset CHARSET = Charset.forName("UTF-8");
    private Type type = Type.I;
    private static HttpLogInterceptor logInterceptor;

    public enum Type {
        W, E, I
    }

    private HttpLogInterceptor() {
    }

    public static HttpLogInterceptor getInstance() {
        if (logInterceptor == null) {
            synchronized (HttpLogInterceptor.class) {
                logInterceptor = (logInterceptor == null) ? new HttpLogInterceptor() : logInterceptor;
            }
        }
        return logInterceptor;
    }

    public HttpLogInterceptor setType(Type type) {
        this.type = type == null ? Type.I : type;
        return this;
    }


    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        boolean cannotPrintLog = false;
        if (cannotPrintLog) {
            return chain.proceed(request);
        }
        //请求日志拦截
        log4Request(request);
        //执行请求，计算请求时间
        long startNs = System.nanoTime();
        Response response;
        try {
            response = chain.proceed(request);
        } catch (Exception e) {
            LogTrack.i(getFullUrl(request) + "  <-- HTTP FAILED: " + e);
            throw e;
        }
        long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);
        //响应日志拦截
        return log4Response(request, response, tookMs);
    }

    @SuppressWarnings({"ConstantConditions", "StringConcatenationInsideStringBufferAppend"})
    private void log4Request(Request request) throws IOException {
        StringBuilder stringBuilder = new StringBuilder();

        RequestBody requestBody = request.body();
        String contentType = "";
        if (requestBody != null && requestBody.contentType() != null) {
            contentType = requestBody.contentType().type() + "" + requestBody.contentType().subtype();
        }
        if (contentType == null || contentType.isEmpty()) {
            contentType = "application/x-www-form-urlencoded";
        }
        try {
            String fullUrlQueryParams = getFullUrl(request);
            stringBuilder.append("\n" + request.method() + "  " + fullUrlQueryParams + "\ncontentType = " + contentType);
            Headers headers = request.headers();
            int count = (headers == null) ? 0 : headers.size();
            stringBuilder.append(count > 0 ? "\n请求头:" : "");
            for (int i = 0; i < count; i++) {
                String name = headers.name(i);
                stringBuilder.append("\n" + name + "=" + headers.value(i));
            }
            String queryParams = request.url().query();
            if (queryParams != null && !queryParams.isEmpty()) {
                stringBuilder.append("\n请求行:\n");
            }
            for (int i = 0; queryParams != null && !queryParams.isEmpty() && i < queryParams.length(); i++) {
                char charAt = queryParams.charAt(i);
                if (charAt != '&') {
                    stringBuilder.append(charAt);
                } else {
                    stringBuilder.append("\n");
                }
            }
            final Request copyRequest = request.newBuilder().build();
            final Buffer buffer = new Buffer();
//            copyRequest.body().writeTo(buffer);
            String readString = buffer.readString(CHARSET);
            if (readString != null && !readString.isEmpty()) {
                String formatBody = getFormatBody(readString);
                stringBuilder.append("\n请求体: " + formatBody);
            }
        } catch (Exception e) {
            LogTrack.e(e);
        }
        printLog("打印请求参数: " + stringBuilder.toString());
    }

    private Response log4Response(Request request, Response response, long tookMs) {
        StringBuilder stringBuilder = new StringBuilder();
        Response.Builder builder = response.newBuilder();
        Response cloneResponse = builder.build();
        ResponseBody responseBody = cloneResponse.body();

        try {
            stringBuilder.append(cloneResponse.request().method() + ' ' + cloneResponse.request().url() + " (" + tookMs + "ms）");

            Headers headers = cloneResponse.headers();
            for (int i = 0, count = headers.size(); i < count; i++) {
                String name = headers.name(i);
                if (!"User-Agent".equalsIgnoreCase(name) && !"Accept-Charset".equalsIgnoreCase(name) && !"Accept-Language".equalsIgnoreCase(name) && !"Server".equalsIgnoreCase(name) && !"Date".equalsIgnoreCase(name) && !"Content-Type".equalsIgnoreCase(name) && !"Transfer-Encoding".equalsIgnoreCase(name) && !"Content-Length".equalsIgnoreCase(name)) {
                    stringBuilder.append("\n" + name + "=" + headers.value(i));
                }
            }
            String body = responseBody.string();
            stringBuilder.append("\n" + body);
            responseBody = ResponseBody.create(responseBody.contentType(), body);
            printLog("打印返回数据: \n" + stringBuilder.toString());
            return response.newBuilder().body(responseBody).build();
        } catch (Exception e) {
            LogTrack.e(e);
        }

        printLog("打印返回数据: \n" + stringBuilder.toString());
        return response;
    }

    private void printLog(String result) {
        if (Type.E == type) {
            LogTrack.e(result);
        } else if (Type.I == type) {
            LogTrack.i(result);
        } else if (Type.W == type) {
            LogTrack.w(result);
        }
    }


    private String getFormatBody(String body) {
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader reader = null;
        if (body == null || body.length() <= 0) {
            return "";
        }
        try {
            reader = new BufferedReader(new StringReader(body));
            while (true) {
                String contentDispositionLine = reader.readLine();
                if (contentDispositionLine == null) {
                    break;
                }
                if (contentDispositionLine.length() <= 300) {
                    //LogTrack.w(contentDispositionLine);//
                }
                if (!body.contains("Content-Disposition:")) {
                    stringBuilder.append("\n");
                    for (int i = 0; i < contentDispositionLine.length(); i++) {
                        char charAt = contentDispositionLine.charAt(i);
                        if (charAt != '&') {
                            stringBuilder.append(charAt);
                        } else {
                            stringBuilder.append('\n');
                        }
                    }
                    return stringBuilder.toString();
                }
                if (contentDispositionLine.startsWith("Content-Disposition:")) {
                    String tmpLine = reader.readLine();
                    String contentLengthLine;
                    String contentTypeLine = "";
                    if (tmpLine.startsWith("Content-Type")) {
                        contentLengthLine = reader.readLine();
                        contentTypeLine = tmpLine;
                    } else {
                        contentLengthLine = tmpLine;
                    }
                    int length = toInt(contentLengthLine.substring("Content-Length:".length(), contentLengthLine.length()));
                    reader.readLine();
                    String contentValue = reader.readLine();
                    if (length < 1024) {
                        contentValue = "Content-Value: " + contentValue;

                    } else {
                        contentValue = "Content-Value: 富媒体文件 0101010101010101";
                    }
                    if (contentTypeLine != null && contentTypeLine.length() > 0) {
                        stringBuilder.append(contentDispositionLine + "\n" + contentTypeLine + "\n" + contentLengthLine + "\n" + contentValue + "\n7533c20a-9a0b-4c3d-8e3d-c0af3fae4d32\n");
                    } else {
                        stringBuilder.append(contentDispositionLine + "\n" + contentLengthLine + "\n" + contentValue + "\n7533c20a-9a0b-4c3d-8e3d-c0af3fae4d32\n");
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                reader.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return stringBuilder.toString();
    }

    private String getFullUrl(Request request) {
        String fullUrlQueryParams = request.url().toString();
        boolean containsY = fullUrlQueryParams.contains("?");
        if (containsY) {
            int indexOf = fullUrlQueryParams.indexOf("?");
            fullUrlQueryParams = fullUrlQueryParams.substring(0, indexOf);
        }
        return fullUrlQueryParams;
    }

    private static int toInt(String text) {
        try {
            return Integer.parseInt((trim(text)));
        } catch (Exception ex) {
            ex.printStackTrace();
            return -1;
        }
    }

    private static String trim(String text) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; text != null && i < text.length(); i++) {
            char charAt = text.charAt(i);
            if (charAt != ' ') {
                builder.append(charAt);
            }
        }
        return builder.toString();
    }
}
